home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
emulator
/
bsvc-1.000
/
bsvc-1
/
bsvc-1.0.4
/
src
/
SimHector
/
cpu
/
RegisterTransfer.cxx
< prev
Wrap
C/C++ Source or Header
|
1995-07-26
|
14KB
|
384 lines
///////////////////////////////////////////////////////////////////////////////
//
// File: RegisterTransfer.cxx (Part of ControlUnit Class)
//
// Purpose: This module contains the register transfer functions
// for the HECTOR simulator. These functions
// execute the register transfer operations called by
// the instruction execution functions in instexec.c
// by setting latches, selecting registers, setting
// muxes, and selecting the alu operation. Also
// included are the functions called by the register
// transfer functions. NOTE that none of these
// functions actually perform the data path operations,
// they simply set up for the Clock() function to do
// the data path operation in proper order. Therefore,
// the sequence of instructions in these functions is
// arbitrary
//
// Author: Greg DeHoogh
//
// Modified: Bradford W. Mott
//
// Date: 17 February 1990
//
// History: Spring 1990 -- Creation
//
// December 4,1993 - Modified for use with BSVC
//
///////////////////////////////////////////////////////////////////////////////
#include "ControlUnit.hxx"
///////////////////////////////////////////////////////////////////////////////
// reg_a -> reg_b
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_reg(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn(PASS_A_NCC);
data_path.alu_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// (reg_a) -> reg_b
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_indirect_to_reg(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.mar_sel(A_BUS);
data_path.mar_latch();
data_path.mar_out_en();
data_path.db_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a -> (reg_b)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_reg_indirect(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.mar_sel(B_BUS);
data_path.mar_latch();
data_path.mar_out_en();
data_path.mdr_sel(A_BUS);
data_path.mdr_latch();
data_path.mdr_out_en();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg -> (mar)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_mar_indirect(int reg)
{
data_path.a_sel(reg);
data_path.mar_out_en();
data_path.mdr_sel(A_BUS);
data_path.mdr_latch();
data_path.mdr_out_en();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// (mar) -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::mar_indirect_to_reg(int reg)
{
data_path.a_sel(reg);
data_path.mar_out_en();
data_path.db_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// mdr -> (mar)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::mdr_to_mar_indirect(void)
{
data_path.mar_out_en();
data_path.mdr_out_en();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg + 1 -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::inc_reg(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(INC_A_NCC);
data_path.alu_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a OP reg_b -> reg_b
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_op_reg_to_reg(int reg_a, int reg_b)
{
int OP = data_path.ir >> 12;
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn((ALUFunction)OP);
data_path.alu_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a OP reg_b -> mdr
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_op_reg_to_mdr(int reg_a, int reg_b)
{
int OP = data_path.ir >> 12;
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn((ALUFunction)OP);
data_path.mdr_sel(ALU_BUS);
data_path.mdr_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a + reg_b -> reg_b
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_plus_reg_to_reg(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn(ADD_NCC);
data_path.alu_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a + reg_b -> mar
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_plus_reg_to_mar(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn(ADD_NCC);
data_path.mar_sel(ALU_BUS);
data_path.mar_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg - 1 -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::dec_reg(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(DEC_A_NCC);
data_path.alu_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a OP reg_b
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_op_reg(int reg_a, int reg_b)
{
int OP = data_path.ir >> 12;
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn((ALUFunction)OP);
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// op reg -> reg (op obtained from OP and DM fields)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::op_reg_to_reg(int reg)
{
int OP = data_path.ir >> 12;
int DM = (data_path.ir & 0x0300) >> 8;
data_path.a_sel(reg);
data_path.alu_fn((ALUFunction)((OP << 4) | DM));
data_path.alu_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// op reg -> mdr (op obtained from OP and DM fields)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::op_reg_to_mdr(int reg)
{
int OP = data_path.ir >> 12;
int DM = (data_path.ir & 0x0300) >> 8;
data_path.a_sel(reg);
data_path.alu_fn((ALUFunction)((OP << 4) | DM));
data_path.mdr_sel(ALU_BUS);
data_path.mdr_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// swap(reg) -> reg (swaps high byte and low byte)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::swap_reg_to_reg(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn(SWAP_A);
data_path.alu_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// swap(reg) -> mdr (swaps high byte and low byte)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::swap_reg_to_mdr(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(SWAP_A);
data_path.mdr_sel(ALU_BUS);
data_path.mdr_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// 0 -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::clr_reg(int reg)
{
data_path.a_sel(reg);
data_path.b_sel(reg);
data_path.alu_fn(XOR);
data_path.alu_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// 0 -> mdr
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::clr_mdr(void)
{
data_path.a_sel(0); // note: use of R0 is arbitrary
data_path.b_sel(0);
data_path.alu_fn(XOR);
data_path.mdr_sel(ALU_BUS);
data_path.mdr_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// flags -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::flags_to_reg(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(CC_OUT);
data_path.alu_gt();
data_path.wrt_a();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// flags -> mdr
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::flags_to_mdr(void)
{
data_path.alu_fn(CC_OUT);
data_path.mdr_sel(ALU_BUS);
data_path.mdr_latch();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg -> flags
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_flags(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(A_CC);
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_a -> reg_b (condition codes not affected)
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::pass_reg_to_reg(int reg_a, int reg_b)
{
data_path.a_sel(reg_a);
data_path.b_sel(reg_b);
data_path.alu_fn(PASS_A);
data_path.alu_gt();
data_path.wrt_b();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_s -> (reg_d); reg_d + 1 -> reg_d
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_reg_indirect_with_inc(int reg_s, int reg_d)
{
data_path.a_sel(reg_s);
data_path.b_sel(reg_d);
data_path.alu_fn(INC_B_NCC);
data_path.alu_gt();
data_path.wrt_b();
data_path.mdr_sel(A_BUS);
data_path.mdr_latch();
data_path.mdr_out_en();
data_path.mar_sel(B_BUS);
data_path.mar_latch();
data_path.mar_out_en();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// mdr -> (mar); reg + 1 -> reg
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::mdr_to_mar_indirect_with_inc(int reg)
{
data_path.a_sel(reg);
data_path.alu_fn(INC_A_NCC);
data_path.alu_gt();
data_path.wrt_a();
data_path.mdr_out_en();
data_path.mar_out_en();
return(data_path.Clock());
}
///////////////////////////////////////////////////////////////////////////////
// reg_s -> (reg_d); reg_d - 1 -> reg_d
///////////////////////////////////////////////////////////////////////////////
const char* ControlUnit::reg_to_reg_indirect_with_dec(int reg_s, int reg_d)
{
data_path.a_sel(reg_s);
data_path.b_sel(reg_d);
data_path.alu_fn(DEC_B_NCC);
data_path.alu_gt();
data_path.wrt_b();
data_path.mdr_sel(A_BUS);
data_path.mdr_latch();
data_path.mdr_out_en();
data_path.mar_sel(B_BUS);
data_path.mar_latch();
data_path.mar_out_en();
return(data_path.Clock());
}